package com.bestcem.xm.txtanls.dao.impl.mysql;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Validator;
import com.alibaba.fastjson.JSONArray;
import com.bestcem.xm.common.core.constant.Constants;
import com.bestcem.xm.common.core.uitls.DateUtil;
import com.bestcem.xm.txtanls.dao.TopicDao;
import com.bestcem.xm.txtanls.dao.mapper.KeywordMapper;
import com.bestcem.xm.txtanls.dao.mapper.TopicMapper;
import com.bestcem.xm.txtanls.entity.mysql.TopicEntity;
import com.bestcem.xm.txtanls.entity.pojo.TopicDO;
import com.bestcem.xm.txtanls.entity.pojo.TopicGroupInfoDO;
import com.bestcem.xm.txtanls.enums.TopicStatusEnum;
import com.bestcem.xm.txtanls.enums.TopicTypeEnum;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;

import static com.bestcem.xm.common.core.constant.Constants.DEFAULT_TOPIC_GROUP_NAME;
import static com.bestcem.xm.common.core.constant.Constants.EMPTY;

/**
 * TopicDao mysql实现
 *
 * @author hang.li <hang.li@idiaoyan.com>
 * @version v1.0
 * @date 2021/9/27 14:13
 */
@Repository
public class TopicDaoImpl implements TopicDao {

    @Resource
    private TopicMapper topicMapper;

    @Resource
    private KeywordMapper keywordMapper;

    @Override
    public TopicDO saveTopic(TopicDO topic) {
        String topicId = new ObjectId().toHexString();
        TopicEntity topicDO = topicToDo(topic);
        topicDO.setTopicId(topicId);
        topicMapper.insertTopic(topicDO);
        topic.setId(topicId);
        return topic;
    }

    @Override
    public TopicDO insertTopic(String projectId, String name, String groupId, List<String> keywords) {
        TopicDO topicDO = new TopicDO(projectId, name, groupId, TopicTypeEnum.TOPIC.getIndex(), TopicStatusEnum.NO_TRAIN.getIndex(), keywords);
        topicDO.setCreatedDate(DateUtil.getCommonDate());
        topicDO.setUpdatedDate(DateUtil.getCommonDate());
        return this.saveTopic(topicDO);
    }

    @Override
    public TopicDO insertGroup(String projectId, String name) {
        TopicDO topicDO = new TopicDO(projectId, name, "", TopicTypeEnum.GROUP.getIndex(), TopicStatusEnum.NO_TRAIN.getIndex());
        topicDO.setCreatedDate(DateUtil.getCommonDate());
        topicDO.setUpdatedDate(DateUtil.getCommonDate());
        return this.saveTopic(topicDO);
    }

    @Override
    public TopicDO getById(String id) {
        return topicConvert(topicMapper.findTopicById(id));
    }

    @Override
    public TopicDO createDefaultTopicGroup(String projectId) {
        TopicDO topicDO = new TopicDO();
        topicDO.setProjectId(projectId);
        topicDO.setType(TopicTypeEnum.GROUP.getIndex());
        topicDO.setTopicGID(EMPTY);
        topicDO.setName(DEFAULT_TOPIC_GROUP_NAME);
        topicDO.setStatus(TopicStatusEnum.NO_TRAIN.getIndex());
        topicDO.setCreatedDate(DateUtil.getCommonDate());
        topicDO.setUpdatedDate(DateUtil.getCommonDate());
        return this.saveTopic(topicDO);
    }

    @Override
    public TopicDO getDefaultTopicGroup(String projectId) {
        TopicEntity topicDO = new TopicEntity();
        topicDO.setProjectId(projectId).setType(TopicTypeEnum.GROUP.getIndex()).setName(DEFAULT_TOPIC_GROUP_NAME);
        List<TopicEntity> topicList = topicMapper.findTopicList(topicDO);
        if (!CollectionUtils.isEmpty(topicList)) {
            return topicConvert(topicList.get(0));
        }
        return null;
    }

    @Override
    public List<TopicDO> listTopicByType(String projectId, Integer type) {
        TopicEntity topicDO = new TopicEntity();
        topicDO.setProjectId(projectId);
        if (Validator.isNotEmpty(type)) {
            topicDO.setType(type);
        }
        List<TopicDO> topicList = new ArrayList<>();
        List<TopicEntity> topicDOList = topicMapper.findTopicList(topicDO);
        if (!CollectionUtils.isEmpty(topicDOList)) {
            for (TopicEntity topic : topicDOList) {
                topicList.add(topicConvert(topic));
            }
        }
        return topicList;
    }

    @Override
    public List<TopicDO> listTopicByKeywordExist(String projectId) {
        TopicEntity topicDO = new TopicEntity();
        topicDO.setProjectId(projectId).setType(TopicTypeEnum.TOPIC.getIndex());
        List<TopicDO> topicList = new ArrayList<>();
        List<TopicEntity> topicDOList = topicMapper.findTopicList(topicDO);
        if (!CollectionUtils.isEmpty(topicDOList)) {
            for (TopicEntity topic : topicDOList) {
                if (StringUtils.isNotBlank(topic.getKeywords())) {
                    topicList.add(topicConvert(topic));
                }
            }
        }
        return topicList;
    }

    @Override
    public List<TopicDO> listTopicByProjectId(String projectId) {
        return listTopicByType(projectId, null);
    }

    @Override
    public List<TopicDO> listTopicByGid(String topicGid) {
        TopicEntity topicDO = new TopicEntity().setGroupId(topicGid);
        List<TopicDO> topicList = new ArrayList<>();
        List<TopicEntity> topicDOList = topicMapper.findTopicList(topicDO);
        if (!CollectionUtils.isEmpty(topicDOList)) {
            for (TopicEntity topic : topicDOList) {
                topicList.add(topicConvert(topic));
            }
        }
        return topicList;
    }

    @Override
    public boolean deleteProjectAllTopic(String projectId) {
        int count = topicMapper.deleteTopicByProjectId(projectId);
        return count > Constants.INT_ZERO;
    }

    @Override
    public Set<String> listTopicKeyword(String projectId) {
        List<TopicDO> topicDOList = this.listTopicByType(projectId, TopicTypeEnum.TOPIC.getIndex());
        Set<String> keywords = new HashSet<>();
        for (TopicDO topicDO : topicDOList) {
            if (!CollectionUtils.isEmpty(topicDO.getKeyDict())) {
                keywords.addAll(topicDO.getKeyDict());
            }
        }
        return keywords;
    }

    @Override
    public long countByName(String projectId, String name) {
        return topicMapper.getTotalByProjectIdAndName(projectId, name);
    }

    @Override
    public boolean updateTopicGIdByGId(String oldGroupId, String newGroupId, String projectId) {
        long count = topicMapper.updateGroupIdByProjectId(oldGroupId, newGroupId, projectId, DateUtil.getCommonDate());
        return count > Constants.INT_ZERO;
    }

    @Override
    public boolean deleteById(String id) {
        int count = topicMapper.deleteTopicById(id);
        return count > Constants.INT_ZERO;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean updateNameOrKeywords(String id, String name, List<String> keywords) {
        if (StringUtils.isNotBlank(name)) {
            long count = topicMapper.updateNameById(id, name, DateUtil.getCommonDate());
            return count > Constants.INT_ZERO;
        }

        String keywordStr = null;
        if (CollUtil.isNotEmpty(keywords)) {
            keywordStr = JSONArray.toJSONString(keywords);
        }
        long count = topicMapper.updateKeywordById(id, keywordStr, DateUtil.getCommonDate());
        return count > Constants.INT_ZERO;
//        if (CollUtil.isNotEmpty(keywords)) {
//            keywordMapper.deleteKeywordsByTopicId(id);
//            List<KeywordEntity> keywordDOList = new ArrayList<>();
//            for (String keyword : keywords) {
//                KeywordEntity keywordDO = new KeywordEntity();
//                keywordDO.setKeyword(new ObjectId().toHexString())
//                        .setTopicId(id)
//                        .setKeyword(keyword);
//                keywordDOList.add(keywordDO);
//            }
//            long count = keywordMapper.insertKeywords(keywordDOList);
//            return count > Constants.INT_ZERO;
//        }
//        return false;
    }

    @Override
    public boolean updateKeyword(String id, List<String> keywords) {

        topicMapper.updateKeywordById(id, CollUtil.isEmpty(keywords) ? null : JSONArray.toJSONString(keywords), DateUtil.getCommonDate());

        return true;
    }

    @Override
    public void appendKeywords(String id, String name, List<String> keywords) {
        TopicEntity topicDO = new TopicEntity().setTopicId(id).setName(name).setType(TopicTypeEnum.TOPIC.getIndex());
        List<TopicEntity> topicList = topicMapper.findTopicList(topicDO);
        if (!CollectionUtils.isEmpty(topicList)) {
            TopicEntity topicEntity = topicList.get(0);
            String dbKeywords = topicEntity.getKeywords();
            List<String> dbKeywordStringList = new ArrayList<>(10);
            if (StringUtils.isNotEmpty(dbKeywords)) {
                dbKeywordStringList = JSONArray.parseArray(dbKeywords, String.class);
            }
            HashSet<String> keywordSet = new HashSet<>();
            keywordSet.addAll(dbKeywordStringList);

            keywordSet.addAll(keywords);
            if (!Objects.equals(dbKeywordStringList.size(), keywordSet.size())) {
                topicMapper.updateKeywordById(topicEntity.getTopicId(), JSONArray.toJSONString(keywordSet), DateUtil.getCommonDate());
            }
        }
    }

    @Override
    public boolean updateGroupIdById(String id, String topicGroupId) {
        long count = topicMapper.updateGroupIdById(id, topicGroupId, DateUtil.getCommonDate());
        return count > Constants.INT_ZERO;
    }

    @Override
    public List<TopicGroupInfoDO> aggregateTopic(String projectId) {
        List<TopicEntity> allTopic = topicMapper.findAllTopic(projectId);
        List<TopicGroupInfoDO> infoList = new ArrayList<>();
        if (CollUtil.isNotEmpty(allTopic)) {
            for (TopicEntity topic : allTopic) {
                TopicGroupInfoDO topicGroupInfoDO = new TopicGroupInfoDO();
                topicGroupInfoDO.setId(topic.getTopicId());
                topicGroupInfoDO.setProjectId(topic.getProjectId());
                topicGroupInfoDO.setName(topic.getName());
                topicGroupInfoDO.setTopicGID(topic.getGroupId());
                topicGroupInfoDO.setType(topic.getType());
                topicGroupInfoDO.setStatus(topic.getStatus());
                List<TopicEntity> topics = topic.getTopics();
                List<TopicDO> topicDOList = new ArrayList<>(10);
                if (CollUtil.isNotEmpty(topics)) {
                    for (TopicEntity topicDo : topics) {
                        topicDOList.add(topicConvert(topicDo));
                    }
                }
                topicGroupInfoDO.setTopicDOList(topicDOList);
                infoList.add(topicGroupInfoDO);
            }
        }
        return infoList;
    }

    @Override
    public boolean moveTopicToDefaultGroup(String topicGId, String projectId) {
        List<TopicDO> topicDOList = this.listTopicByGid(topicGId);
        if (CollectionUtils.isEmpty(topicDOList)) {
            return true;
        }
        TopicDO topicDO = this.getDefaultTopicGroup(projectId);
        if (ObjectUtils.isEmpty(topicDO)) {
            topicDO = this.createDefaultTopicGroup(projectId);
        }
        return this.updateTopicGIdByGId(topicGId, topicDO.getId(), projectId);
    }


    /**
     * 话题转换方法
     *
     * @param topic
     * @return
     */
    private TopicEntity topicToDo(TopicDO topic) {
        TopicEntity topicDO = new TopicEntity();
        topicDO.setProjectId(topic.getProjectId())
                .setName(topic.getName())
                .setGroupId(topic.getTopicGID())
                .setType(topic.getType())
                .setKeywords(CollUtil.isEmpty(topic.getKeyDict()) ? null : JSONArray.toJSONString(topic.getKeyDict()))
                .setStatus(topic.getStatus())
                .setCreatorId(topic.getCreatedId())
                .setOperatorId(topic.getUpdatedId())
                .setCreateTime(DateUtil.getCommonDate())
                .setUpdateTime(DateUtil.getCommonDate())
                .setSample(topic.getSample());
        return topicDO;
    }

    /**
     * 话题转换方法
     *
     * @param topicDO
     * @return
     */
    private TopicDO topicConvert(TopicEntity topicDO) {
        if (Objects.nonNull(topicDO)) {
            TopicDO topic = new TopicDO();
            topic.setId(topicDO.getTopicId());
            topic.setProjectId(topicDO.getProjectId());
            topic.setTopicGID(topicDO.getGroupId());
            topic.setName(topicDO.getName());
            topic.setType(topicDO.getType());
            topic.setStatus(topicDO.getStatus());
            topic.setCreatedDate(topicDO.getCreateTime());
            topic.setUpdatedDate(topicDO.getUpdateTime());
            topic.setCreatedId(topicDO.getCreatorId());
            topic.setUpdatedId(topicDO.getOperatorId());
            if (StringUtils.isNotBlank(topicDO.getKeywords())) {
                List<String> keyDict = JSONArray.parseArray(topicDO.getKeywords(), String.class);
                topic.setKeyDict(keyDict);
            }
            return topic;
        }
        return null;
    }
}
